#include "main.h"
#include "lwip/tcp.h"

#define LOG_LINE(...) do { printf(__VA_ARGS__); printf("\r\n"); } while(0)
 
struct tcp_pcb *tcp_server = NULL;
uint8_t recv_test_buf[1024];

struct ip4_addr_fmt {
    uint32_t addr1 : 8;
    uint32_t addr2 : 8;
    uint32_t addr3 : 8;
    uint32_t addr4 : 8;
};

err_t tcp_server_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err);
err_t tcp_server_recv_cb(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
void tcp_err_cb(void *arg, err_t err);

void tcp_server_init(void)
{
    err_t err;

    tcp_server = tcp_new();  /* 创建TCP控制块 */ 
    if (tcp_server == NULL)
    {
        LOG_LINE("failed to new tcp pcb");
        return;
    }

    err = tcp_bind(tcp_server, IP_ADDR_ANY, 8080);  /* 绑定IP端口 */ 
    if (err != ERR_OK)
    {
        LOG_LINE("failed to bind tcp");
        tcp_close(tcp_server);  
        return;
    }

    tcp_server = tcp_listen(tcp_server);    /* 启用接听 */ 

    tcp_accept(tcp_server, tcp_server_accept_cb); /* 设置收到客户端连接请求的回调函数 */
    LOG_LINE("TCP Server OK!!!");
    return;
}

err_t tcp_server_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err)
{
    struct ip4_addr_fmt *ip = (struct ip4_addr_fmt *)&newpcb->remote_ip;
    LOG_LINE("Client Connected from %d.%d.%d.%d/%d", ip->addr1, ip->addr2, ip->addr3, ip->addr4, newpcb->remote_port);
    tcp_recv(newpcb, tcp_server_recv_cb);
    tcp_err(newpcb, tcp_err_cb);

    return ERR_OK; /* 记得return ERR_OK,很重要/(ㄒoㄒ)/~~ */
}

err_t tcp_server_recv_cb(void *arg, struct tcp_pcb *tpcb,
                         struct pbuf *p, err_t err)
{

    if (p != NULL)
    {
        struct pbuf *q;
        int recv_count = 0;

        tcp_recved(tpcb, p->tot_len); /* 更新接收窗口 */
        for (q = p; q != NULL; q = q->next)
        {
            if (q->len > sizeof(recv_test_buf))
            {
                memcpy(recv_test_buf, q->payload, sizeof(recv_test_buf));
                break;
            }
            else
            {
                if (recv_count >= sizeof(recv_test_buf))
                    break;
                memcpy(&recv_test_buf[recv_count], q->payload, q->len);
                recv_count += q->len;
            }
        }
        pbuf_free(p);
    }
    else if (err == ERR_OK) /* 接收成功但数据包是空的说明客户端断开连接 */
    {
        LOG_LINE("Client Disconnect");
        return tcp_close(tpcb);
    }

    struct ip4_addr_fmt *ip = (struct ip4_addr_fmt *)&tpcb->remote_ip;
    LOG_LINE("recv from %d.%d.%d.%d/%d, msg %s",
             ip->addr1, ip->addr2, ip->addr3, ip->addr4, tpcb->remote_port, recv_test_buf);
    memset(recv_test_buf, 0, sizeof(recv_test_buf));

    return ERR_OK; /* 记得return ERR_OK,很重要/(ㄒoㄒ)/~~ */
}

void tcp_err_cb(void *arg, err_t err)
{

}
